import React from 'react';
import styles from '../index.less';
import bgImg from '@/assets/images/login-background.jpg';

const percent = 1 / 6400;
const distance = 100;
const radius = 150;
const colorValue = (min) => {
  return Math.floor(Math.random() * 255 + min);
};
function GetColor(min) {
  const currentMin = min || 0;
  this.r = colorValue(currentMin);
  this.g = colorValue(currentMin);
  this.b = colorValue(currentMin);
  this.style = `rgba(${this.r}, ${this.g}, ${this.b}, 0.8)`;
}
const mixComponents = (comp1, weight1, comp2, weight2) => {
  return (comp1 * weight1 + comp2 * weight2) / (weight1 + weight2);
};
const averageColorStyles = (dot1, dot2) => {
  const color1 = dot1.color;
  const color2 = dot2.color;
  const r = mixComponents(color1.r, dot1.radius, color2.r, dot2.radius);
  const g = mixComponents(color1.g, dot1.radius, color2.g, dot2.radius);
  const b = mixComponents(color1.b, dot1.radius, color2.b, dot2.radius);
  return `rgba(${Math.floor(r)}, ${Math.floor(g)}, ${Math.floor(b)}, 0.15)`;
};
const moveDots = (dots, width, height) => {
  for (let i = 0; i < dots.length; i++) {
    const dot = dots[i];
    if (dot.y < 0 || dot.y > height) {
      dot.vy = -dot.vy;
    } else if (dot.x < 0 || dot.x > width) {
      dot.vx = -dot.vx;
    }
    dot.x += dot.vx;
    dot.y += dot.vy;
  }
};
const connectDots = (dots, mousePosition, ctx) => {
  for (let i = 0; i < dots.length; i++) {
    for (let j = 0; j < dots.length; j++) {
      const i_dot = dots[i];
      const j_dot = dots[j];
      if (
        i_dot.x - j_dot.x < distance &&
        i_dot.y - j_dot.y < distance &&
        i_dot.x - j_dot.x > -distance &&
        i_dot.y - j_dot.y > -distance
      ) {
        if (
          i_dot.x - mousePosition.x < radius &&
          i_dot.y - mousePosition.y < radius &&
          i_dot.x - mousePosition.x > -radius &&
          i_dot.y - mousePosition.y > -radius
        ) {
          ctx.beginPath();
          ctx.strokeStyle = averageColorStyles(i_dot, j_dot);
          ctx.moveTo(i_dot.x, i_dot.y);
          ctx.lineTo(j_dot.x, j_dot.y);
          ctx.stroke();
          ctx.closePath();
        }
      }
    }
  }
};
const drawDots = (dots, ctx) => {
  for (let i = 0; i < dots.length; i++) {
    const dot = dots[i];
    dot.draw(ctx);
  }
};

function Dot(width, height) {
  this.x = Math.random() * width;
  this.y = Math.random() * height;

  this.vx = -0.5 + Math.random();
  this.vy = -0.5 + Math.random();

  this.radius = Math.random() * 2;

  this.color = new GetColor();
}
Dot.prototype = {
  draw: function (ctx) {
    ctx.beginPath();
    ctx.fillStyle = this.color.style;
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI, false);
    ctx.fill();
  },
};

export default class LoginContainer extends React.Component {
  constructor() {
    super();
    this.state = {
      dotList: [],
      pageSize: {},
      mousePosition: {},
      stamp: '',
    };
    this.canvas = React.createRef();
    this.startAnimate = this.startAnimate.bind(this);
    this.startByResize = this.startByResize.bind(this);
  }

  componentDidMount() {
    this.context2D = this.canvas.current.getContext('2d');
    this.context2D.lineWidth = 0.3;
    this.context2D.strokeStyle = new GetColor(150).style;
    this.start();
    window.addEventListener('resize', this.startByResize);
  }

  componentWillUnmount() {
    if (this.animateId) {
      cancelAnimationFrame(this.animateId);
    }
    window.removeEventListener('resize', this.startByResize, false);
  }

  initDots() {
    return new Promise((resolve) => {
      const canvasDom = this.canvas.current;
      const width = document.body.clientWidth;
      const height = document.body.clientHeight;
      canvasDom.width = width;
      canvasDom.height = height;
      const dotNumber = Math.floor(width * height * percent);
      const currentDots = [];
      for (let i = 0; i < dotNumber; i++) {
        currentDots.push(new Dot(width, height));
      }
      this.setState(
        {
          dotList: currentDots,
          pageSize: { width, height },
          mousePosition: { x: Math.floor(width / 2), y: Math.floor(height / 2) },
        },
        () => {
          resolve();
        },
      );
    });
  }

  startAnimate() {
    const { width, height } = this.state.pageSize;
    this.context2D.clearRect(0, 0, width, height);
    moveDots(this.state.dotList, width, height);
    connectDots(this.state.dotList, this.state.mousePosition, this.context2D);
    drawDots(this.state.dotList, this.context2D);
    this.animateId = requestAnimationFrame(this.startAnimate);
  }

  start() {
    if (this.animateId) {
      cancelAnimationFrame(this.animateId);
    }
    this.initDots().then(() => {
      this.startAnimate();
    });
  }

  startByResize() {
    const stamp = new Date().getTime();
    this.setState({ stamp }, () => {
      this.checkContinuousResize(stamp)
        .then(() => {
          this.start();
        })
        .catch(() => {});
    });
  }

  checkContinuousResize(stamp) {
    return new Promise((resolve, reject) => {
      const _this = this;
      setTimeout(() => {
        if (stamp !== _this.state.stamp) {
          reject();
        } else {
          resolve();
        }
      }, 500);
    });
  }

  handleMouseMove(e) {
    this.setState({
      mousePosition: {
        x: e.pageX,
        y: e.pageY,
      },
    });
  }

  handleMouseLeave() {
    const width = document.body.clientWidth;
    const height = document.body.clientHeight;
    this.setState({
      mousePosition: {
        x: Math.floor(width / 2),
        y: Math.floor(height / 2),
      },
    });
  }

  render() {
    const { children } = this.props;
    return (
      <div
        className={styles.loginContainer}
        onMouseMove={this.handleMouseMove.bind(this)}
        onMouseLeave={this.handleMouseLeave.bind(this)}
      >
        <img src={bgImg} className={styles.loginBgImg} />
        <canvas ref={this.canvas} className={styles.loginCanvas} width={1920} height={1080} />
        {children}
      </div>
    );
  }
}
